package main

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	log "github.com/sirupsen/logrus"
	viper2 "github.com/spf13/viper"
	"httpserver/metrics"
	"io"
	"math/rand"
	"net"
	"net/http"
	"strings"
	"time"
)

var logLevel string

func main() {
	metrics.Register() //注册Metric
	httpserverConf := "/etc/httpserver/httpserverconf.properties"
	log.Info("confFile is " + httpserverConf)
	logLevel = get("httpserverconf.log_level").(string)
	level, err := log.ParseLevel(logLevel)
	if err != nil {
		level = log.GetLevel()
	}
	log.SetLevel(level)
	myconf := get("httpserverconf.logconf").(string)
	log.Trace(myconf + " in viperLoadConf")
	log.Debug(myconf + " in viperLoadConf")
	log.Info(myconf + " in viperLoadConf")
	log.Warn(myconf + " in viperLoadConf")
	log.Error(myconf + " in viperLoadConf")

	port := get("httpserverconf.port").(string)
	log.Info("httpserver listend port: ", port)

	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/healthz", healthz)
	mux.HandleFunc("/hello", httpHandler)
	mux.Handle("/metrics", promhttp.Handler())

	srv := http.Server{}
	srv.Addr = ":" + port
	srv.Handler = mux

	err = srv.ListenAndServe()

	if err != nil {
		log.Fatal(err)
	}

}

func get(fileKey string) interface{} {
	index := strings.Index(fileKey, ".")
	fmt.Print(fileKey)
	fileName := fileKey[0:index]
	key := fileKey[index+1:]

	viper := viper2.New()
	viper.SetConfigName(fileName)
	viper.SetConfigType("properties")
	viper.AddConfigPath("./etc/httpserver")

	if err := viper.ReadInConfig(); err != nil {
		panic(err.Error())
	}
	return viper.Get(key)
}

func healthz(w http.ResponseWriter, r *http.Request) {
	fmt.Println("entering healthz handler")
	//当访问localhost/healthz 时，返回 200
	io.WriteString(w, "200\n")
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("entering root handler")
	myconf := get("httpserverconf.logconf").(string)
	log.Trace(myconf)
	log.Debug(myconf)
	log.Info(myconf)
	log.Warn(myconf)
	log.Error(myconf)
	user := r.URL.Query().Get("user")
	if user != "" {
		io.WriteString(w, fmt.Sprintf("hello [%s]\n", user))
	} else {
		io.WriteString(w, "hello [stranger]\n")
	}
	//将request中带的header写入response header
	io.WriteString(w, "===================Details of the http request header:============\n")
	for k, v := range r.Header {
		io.WriteString(w, fmt.Sprintf("%s=%s\n", k, v))
	}
	//获取环境变量VERSION，并写入response header
	ver := get("httpserverconf.VERSION")
	io.WriteString(w, fmt.Sprintf("The OS env var VERSION is: %v", ver))
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		fmt.Println("err:", err)
	}

	if net.ParseIP(ip) != nil {
		log.Info("The client IP is: ", ip)
	}
	log.Info("The status code is: ", http.StatusOK)
}

func httpHandler(w http.ResponseWriter, r *http.Request) {
	log.Info("entering http handler")
	timer := metrics.NewTimer() //添加延时 Metric
	defer timer.ObserveTotal()
	user := r.URL.Query().Get("user")
	delay := randInt(10, 2000) //增加2s的随机延迟
	time.Sleep(time.Millisecond * time.Duration(delay))
	if user != "" {
		io.WriteString(w, fmt.Sprintf("hello [#{user}]\n"))
	} else {
		io.WriteString(w, "hello [stranger]\n")
	}
	io.WriteString(w, "===================Details of the http request header:============\n")
	log.Infof("Respond in %d ms", delay)
}

func randInt(min, max int) int {
	rand.Seed(time.Now().Unix())
	return rand.Intn(max-min) + min
}
